package br.ufrj.dcc.trabxml.manager;

import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.rmi.RemoteException;
import java.util.Collection;
import java.util.List;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.rpc.ServiceException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import br.ufrj.dcc.trabxml.MySender;
import br.ufrj.dcc.trabxml.model.ObjectFactory;
import br.ufrj.dcc.trabxml.model.TLivro;
import br.ufrj.dcc.trabxml.util.EXistConnection;
import br.ufrj.dcc.trabxml.util.Properties;
import br.ufrj.dcc.trabxml.util.TrabUtil;
import br.ufrj.dcc.trabxml.util.XmlUtil;

public class BookManager {

    private static final String ISBNdb_KEY = "ZYODIAZ8";
	public static final String MY_CONTROL = "/controle.xml";
	public static final String MY_CATALOG = "/catalogo.xml";
    
    public boolean doIHaveThisBook(int owner, String isbn) throws Exception{
        EXistConnection conn = new EXistConnection();
        conn.connect();
        boolean resp = false;
        try {
            resp = doIHaveThisBook(conn, owner, isbn);
        } finally {
            conn.disconnect();
        }
        return resp;
    }    
    
    public boolean doIHaveThisBook(EXistConnection conn, int owner, String isbn) throws Exception{
        Collection<TLivro> books = listBooks(conn,"");
        for(TLivro book : books) {
            if (book.getDono().equals(BigInteger.valueOf(owner)) && book.getIsbn().equals(isbn)) {
                return true;
            }
        }
        return false;
    }
    
    /**
     * Retorna o grupo que me emprestou o livro
     * @param owner
     * @param isbn
     * @return de quem veio o livro (ou eu mesmo)
     */
    
    public int getLastGroup(int owner, String isbn) throws Exception {  
        int lastGroup = Integer.parseInt(Properties.instance.getProperty("mygroup"));
        EXistConnection conn = new EXistConnection();
        conn.connect();
        try {
            lastGroup = getLastGroup(conn, owner, isbn);
        } finally {
            conn.disconnect();
        }
        return lastGroup;
    }
    
    /**
     * Retorna o grupo que me emprestou o livro
     * @param conn conexao ativa
     * @param owner
     * @param isbn
     * @return de quem veio o livro (ou eu mesmo)
     */
    
    public int getLastGroup(EXistConnection conn, int owner, String isbn) throws Exception {  
        String xml = conn.gainFile(BookManager.MY_CONTROL);    
        return getLastGroup(xml,owner,isbn);
    } 
    
    /**
     * Retorna o grupo que me emprestou o livro
     * @param conn conexao ativa
     * @param owner
     * @param isbn
     * @return de quem veio o livro (ou eu mesmo)
     */
    
    public int getLastGroup(String xml, int owner, String isbn) throws Exception {
        int myGroup = Integer.parseInt(Properties.instance.getProperty("mygroup"));
        int lastGroup = myGroup;
        Node root = XmlUtil.getDocumentRoot(xml);
        XPath xpath = XPathFactory.newInstance().newXPath();
        Node groupNode = (Node) xpath.evaluate(
                "//emprestimo/remetente[../dono = '"+owner+"' and ../isbn='"+isbn+"' and ../destinatario = '"+myGroup+"']", root, XPathConstants.NODE);
        if (groupNode != null) {
            lastGroup = Integer.parseInt(groupNode.getFirstChild().getNodeValue());
        }        
        return lastGroup;
    }     
    
    /**
     * Retorna o grupo que pegou o livro emprestado ou o meu grupo (se ninguem pegou emprestado)
     * @param owner
     * @param isbn
     * @return com quem estah o livro agora
     */
    
    public int getActualGroup(int owner, String isbn) throws Exception {  
        int actualGroup = Integer.parseInt(Properties.instance.getProperty("mygroup"));
        EXistConnection conn = new EXistConnection();
        conn.connect();
        try {
            actualGroup = getActualGroup(conn, owner, isbn);
        } finally {
            conn.disconnect();
        }
        return actualGroup;
    }
    
    /**
     * Retorna o grupo que pegou o livro emprestado ou o meu grupo (se ninguem pegou emprestado)
     * @param conn conexao ativa
     * @param owner
     * @param isbn
     * @return com quem estah o livro agora
     */
    
    public int getActualGroup(EXistConnection conn, int owner, String isbn) throws Exception {  
        String xml = conn.gainFile(BookManager.MY_CONTROL);     
        return getActualGroup(xml,owner,isbn);
    }    
    
    /**
     * Retorna o grupo que pegou o livro emprestado ou o meu grupo (se ninguem pegou emprestado)
     * @param conn conexao ativa
     * @param owner
     * @param isbn
     * @return com quem estah o livro agora
     */
    
    public int getActualGroup(String xml, int owner, String isbn) throws Exception {  
        int myGroup = Integer.parseInt(Properties.instance.getProperty("mygroup"));
        int actualGroup = myGroup;
        Node root = XmlUtil.getDocumentRoot(xml);
        XPath xpath = XPathFactory.newInstance().newXPath();
        Node groupNode = (Node) xpath.evaluate(
                "//emprestimo/destinatario[../dono = '"+owner+"' and ../isbn='"+isbn+"' and ../remetente='"+myGroup+"']", root, XPathConstants.NODE);
        if (groupNode != null) {
            actualGroup = Integer.parseInt(groupNode.getFirstChild().getNodeValue());
        }        
        return actualGroup;
    }    
    
    /**
     * Remove o livro da lista de emprestimos (devolvido)
     * @param owner
     * @param isbn
     * @throws Exception
     */
    
    public void removeActualGroup(int fromGroup, int toGroup, int owner, String isbn) throws Exception {
        EXistConnection conn = new EXistConnection();
        conn.connect();
        try {
            String xml = conn.gainFile(BookManager.MY_CONTROL);      
            Node root = XmlUtil.getDocumentRoot(xml);
            XPath xpath = XPathFactory.newInstance().newXPath();
            Node node = (Node) xpath.evaluate(
                    "//emprestimo[dono = '"+owner+"' and isbn='"+isbn+"' and remetente='"+fromGroup+"' and destinatario='"+toGroup+"']", root, XPathConstants.NODE);
            if (node != null) { 
                node.getParentNode().removeChild(node);
            }          
            conn.storeFile(BookManager.MY_CONTROL, XmlUtil.prettyPrint(root.getOwnerDocument()));
        } finally {
            conn.disconnect();      
        }
    }
    
    /**
     * Grava um emprestimo
     * @param actualGroup quem pegou emprestado (pode ser eu mesmo (devolucao)
     * @param owner
     * @param isbn
     */
    
    public void addActualGroup(int lastGroup, int actualGroup, int owner, String isbn) throws Exception {        
        EXistConnection conn = new EXistConnection();
        conn.connect();
        try {
            addActualGroup(conn, lastGroup, actualGroup, owner, isbn);
        } finally {
            conn.disconnect();      
        }
    }    
    
    /**
     * Grava um emprestimo
     * @param conn - conexao ativa
     * @param actualGroup quem pegou emprestado (pode ser eu mesmo (devolucao)
     * @param owner
     * @param isbn
     */
    
    public void addActualGroup(EXistConnection conn, int lastGroup, int actualGroup, int owner, String isbn) throws Exception {        
        String xml = conn.gainFile(BookManager.MY_CONTROL);
        Node root = XmlUtil.getDocumentRoot(xml);
        if (actualGroup != lastGroup) {
            Node node = root.getOwnerDocument().createElement("emprestimo");
            Node ownerNode = root.getOwnerDocument().createElement("dono");
            ownerNode.appendChild(root.getOwnerDocument().createTextNode(Integer.toString(owner)));
            Node isbnNode = root.getOwnerDocument().createElement("isbn");
            isbnNode.appendChild(root.getOwnerDocument().createTextNode(isbn));
            Node lastGroupNode = root.getOwnerDocument().createElement(
                    "remetente");
            lastGroupNode.appendChild(root.getOwnerDocument().createTextNode(Integer.toString(lastGroup)));
            Node groupNode = root.getOwnerDocument().createElement(
                    "destinatario");
            groupNode.appendChild(root.getOwnerDocument().createTextNode(Integer.toString(actualGroup)));
            node.appendChild(ownerNode);
            node.appendChild(isbnNode);
            node.appendChild(lastGroupNode);
            node.appendChild(groupNode);
            root.appendChild(node);
        }
        xml = XmlUtil.prettyPrint(root.getOwnerDocument());
        System.out.println(xml);
        conn.storeFile(BookManager.MY_CONTROL, xml);
    }        
    
    public void deleteBook(String isbn) throws Exception{
        deleteBook(Integer.parseInt(Properties.instance.getProperty("mygroup")),isbn);
    }
    
    public void deleteBook(int owner, String isbn) throws Exception{
        int mygroup = Integer.parseInt(Properties.instance.getProperty("mygroup"));
        EXistConnection conn = new EXistConnection();
        conn.connect();
        String xml = conn.gainFile(BookManager.MY_CATALOG);
        Node root = XmlUtil.getDocumentRoot(xml);
        XPath xpath = XPathFactory.newInstance().newXPath();
        Node book = (Node) xpath.evaluate(
                "//livro[(isbn='"+isbn+"') and (dono='"+owner+"')]", root, XPathConstants.NODE);
        if (book == null) {
            conn.disconnect();
            throw new Exception("Livro inexistente!");
        }
        int actualGroup = getActualGroup(owner,isbn);
        if (actualGroup != mygroup) {
            conn.disconnect();
            throw new Exception("Livro emprestado para o grupo "+actualGroup+".");
        }        
        book.getParentNode().removeChild(book);
        xml = XmlUtil.prettyPrint(root.getOwnerDocument());
        conn.storeFile(BookManager.MY_CATALOG, xml);
        conn.disconnect();
    }    
    
    /**
     * Eu emprestando meu livro para alguem
     * @param group
     * @param owner
     * @param isbn
     * @throws Exception
     */
    
    public boolean lendMyBook(int group, int owner, String isbn){
        int myGroup = Integer.parseInt(Properties.instance.getProperty("mygroup"));
        EXistConnection conn = new EXistConnection();
        try {
            conn.connect();
            if (!doIHaveThisBook(conn,owner, isbn)){
            	HistoryManager.getInstance().addRecord(HistoryManager.TYPE_LENDING, group, myGroup, owner, false, isbn);
                throw new Exception("Livro nao encontrado!");
            }
            int actualGroup = getActualGroup(conn,owner, isbn);
            if ((myGroup != actualGroup) && (group != actualGroup)){
            	HistoryManager.getInstance().addRecord(HistoryManager.TYPE_LENDING, group, myGroup, owner, false, isbn);
                throw new Exception("Este livro ja foi emprestado.");
            }
            if (myGroup == actualGroup) {
                addActualGroup(conn,myGroup, group, owner, isbn);
            }
            
            HistoryManager.getInstance().addRecord(HistoryManager.TYPE_LENDING, group, myGroup, owner, true, isbn);
            
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                conn.disconnect();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return true;
    }
    
    /**
     *  Eu pedindo um livro emprestado
     * @param group
     * @param owner
     * @param isbn
     * @param title
     * @param publisher
     * @param authors
     * @param obs
     * @throws Exception
     */
    
    public void lendBook(int group, int owner, String isbn, String title, String publisher, List<String> authors, String obs) throws Exception {
    	int myGroup = Integer.parseInt(Properties.instance.getProperty("mygroup"));
    	
        EXistConnection conn = new EXistConnection();
        conn.connect();
        try {
            if (doIHaveThisBook(conn,owner, isbn)){
                throw new Exception("Este livro ja existe no cadastro.");
            }
            String req = XmlManager.createLendRequest(group, owner,isbn);
            String xml = MySender.send(TrabUtil.getGroupHost(group), TrabUtil.getGroupPort(group), req);
            if (xml == null) {
            	HistoryManager.getInstance().addRecord(HistoryManager.TYPE_LENDING, myGroup, group, owner, false, isbn);
                throw new Exception("Sem resposta.");
            }
            Node root = XmlUtil.getDocumentRoot(xml);
            XPath xpath = XPathFactory.newInstance().newXPath();
            if (xpath.evaluate("//resposta[codigo/text() = '1']", root, XPathConstants.NODE) == null) {
            	HistoryManager.getInstance().addRecord(HistoryManager.TYPE_LENDING, myGroup, group, owner, false, isbn);
                throw new Exception("Emprestimo nao confirmado.");
            }
            ObjectFactory factory = new ObjectFactory();        
            TLivro book = factory.createTLivro();
            book.setDono(BigInteger.valueOf(owner));
            book.setIsbn(isbn);
            book.setTitulo(title);
            book.setEditora(publisher);
            book.getAutor().addAll(authors);
            book.setObs(obs);        
            addBook(book);
            
            addActualGroup(conn,group, myGroup, owner, isbn);
            
            HistoryManager.getInstance().addRecord(HistoryManager.TYPE_LENDING, myGroup, group, owner, true, isbn);
            
        } finally {
            conn.disconnect();
        }
    }
    
    /**
     * Eu pegando um livro de volta
     * @param owner
     * @param isbn
     * @throws Exception
     */
    
    public void takeBookBack(int actualGroup, int owner, String isbn) throws Exception{
        int myGroup = Integer.parseInt(Properties.instance.getProperty("mygroup"));
        EXistConnection conn = new EXistConnection();
        conn.connect();
        try {    
            if (!doIHaveThisBook(conn, owner, isbn)) {
            	HistoryManager.getInstance().addRecord(HistoryManager.TYPE_BOOKRETURN, myGroup, actualGroup, owner, false, isbn);
                throw new Exception("Livro nao encontrado.");
            }
            String req = XmlManager.createReturnRequest(actualGroup, owner, isbn);
            String xml = MySender.send(TrabUtil.getGroupHost(actualGroup), TrabUtil.getGroupPort(actualGroup), req);
            if (xml == null) {
            	HistoryManager.getInstance().addRecord(HistoryManager.TYPE_BOOKRETURN, myGroup, actualGroup, owner, false, isbn);
                throw new Exception("Devolucao nao confirmada. Grupo "+actualGroup+" nao responde.");
            }
            Node root = XmlUtil.getDocumentRoot(xml);
            XPath xpath = XPathFactory.newInstance().newXPath();
            if (xpath.evaluate("//resposta[codigo/text() = '3']", root,XPathConstants.NODE) == null) {
            	HistoryManager.getInstance().addRecord(HistoryManager.TYPE_BOOKRETURN, myGroup, actualGroup, owner, false, isbn);
                throw new Exception("Grupo "+actualGroup+" nao confirmou a devolucao.");
            }
            removeActualGroup(myGroup, actualGroup, owner, isbn);
            
            HistoryManager.getInstance().addRecord(HistoryManager.TYPE_BOOKRETURN, actualGroup, myGroup, owner, true, isbn);
           
        } finally {
            conn.disconnect();
        }      
    }    
    
    /**
     * Eu retornando o livro para alguem
     * @param owner
     * @param isbn
     * @throws Exception
     */
    
    public void returnBook(int owner, String isbn) throws Exception{
        int myGroup = Integer.parseInt(Properties.instance.getProperty("mygroup"));
        EXistConnection conn = new EXistConnection();
        conn.connect();
        try {    
            if (!doIHaveThisBook(conn, owner, isbn)) {
                throw new Exception("Livro nao encontrado.");
            }
            int group = getLastGroup(conn, owner, isbn);//pegar quem me emprestou o livro
            if (group == myGroup) {
            	HistoryManager.getInstance().addRecord(HistoryManager.TYPE_BOOKRETURN, myGroup, group, owner, false, isbn);
                throw new Exception("Livro nao pode ser devolvido.");
            }
            String req = XmlManager.createReturnRequest(group, owner, isbn);
            String xml = MySender.send(TrabUtil.getGroupHost(group), TrabUtil.getGroupPort(group), req);
            if (xml == null) {
            	HistoryManager.getInstance().addRecord(HistoryManager.TYPE_BOOKRETURN, myGroup, group, owner, false, isbn);
                throw new Exception("Devolucao nao confirmada. Grupo "+group+" nao responde.");
            }
            Node root = XmlUtil.getDocumentRoot(xml);
            XPath xpath = XPathFactory.newInstance().newXPath();
            if (xpath.evaluate("//resposta[codigo/text() = '3']", root,XPathConstants.NODE) == null) {
            	HistoryManager.getInstance().addRecord(HistoryManager.TYPE_BOOKRETURN, myGroup, group, owner, false, isbn);
                throw new Exception("Grupo "+group+" nao confirmou a devolucao.");
            }
            removeActualGroup(group, myGroup, owner, isbn);
            deleteBook(owner,isbn);
            
            HistoryManager.getInstance().addRecord(HistoryManager.TYPE_BOOKRETURN, myGroup, group, owner, true, isbn);
            
        } finally {
            conn.disconnect();
        }      
    }
    
    /**
     * aceitando um grupo pedindo seu livro de volta / aceitanto meu livro de volta
     * @param group - quem estah pedindo o livro de volta 
     * @param owner - o dono do livro
     * @param isbn - o isbn do livro
     * @throws Exception
     */
    
    public void acceptBookReturn(int group, int owner, String isbn) throws Exception {
        int myGroup = Integer.parseInt(Properties.instance.getProperty("mygroup"));
        EXistConnection conn = new EXistConnection();
        conn.connect();
        try {
            if (!doIHaveThisBook(conn,owner, isbn)) {
                throw new Exception("Livro nao encontrado.");
            }
            int actualGroup = getActualGroup(conn,owner, isbn);
            if (actualGroup == group) {//outro grupo querendo devolver pra mim
                if (group == myGroup) {
                	HistoryManager.getInstance().addRecord(HistoryManager.TYPE_BOOKRETURN, group, myGroup, owner, false, isbn);
                    throw new Exception("Eu pedindo pra devolver livro pra mim mesmo!!! Esta mensagem nao deveria ser exibida.");
                }
                
                HistoryManager.getInstance().addRecord(HistoryManager.TYPE_BOOKRETURN, group, myGroup, owner, true, isbn);
                removeActualGroup(myGroup, group, owner, isbn);
                conn.disconnect();
                return;
            }
            
            //abortar se quem tiver pedindo o livro de volta nao foi quem me emprestou
            int fromGroup = getLastGroup(conn, owner, isbn);
            if (fromGroup != group) {
            	HistoryManager.getInstance().addRecord(HistoryManager.TYPE_BOOKRETURN, myGroup, group, owner, false, isbn);
                throw new Exception("Acesso negado.");
            }
            if (actualGroup != myGroup) {//devolvendo para mim
                String req = XmlManager.createReturnRequest(actualGroup, owner, isbn);
                String xml = MySender.send(TrabUtil.getGroupHost(actualGroup), TrabUtil.getGroupPort(actualGroup), req);
                if (xml == null) {
                	HistoryManager.getInstance().addRecord(HistoryManager.TYPE_BOOKRETURN, actualGroup, myGroup, owner, false, isbn);
                    throw new Exception("Devolucao nao confirmada. Grupo "+actualGroup+" nao responde.");
                }
                Node root = XmlUtil.getDocumentRoot(xml);
                XPath xpath = XPathFactory.newInstance().newXPath();
                if (xpath.evaluate("//resposta[codigo/text() = '3']", root,XPathConstants.NODE) == null) {
                	HistoryManager.getInstance().addRecord(HistoryManager.TYPE_BOOKRETURN, actualGroup, myGroup, owner, false, isbn);
                    throw new Exception("Grupo "+actualGroup+" nao confirmou a devolucao.");
                }     
                
                HistoryManager.getInstance().addRecord(HistoryManager.TYPE_BOOKRETURN, actualGroup, myGroup, owner, true, isbn);
                removeActualGroup(myGroup, actualGroup, owner, isbn);
                actualGroup = myGroup;
            }
            if (group != myGroup) {
            	HistoryManager.getInstance().addRecord(HistoryManager.TYPE_BOOKRETURN, myGroup, group, owner, true, isbn);
                removeActualGroup(group, myGroup, owner, isbn);
                deleteBook(owner,isbn);
            }
        } finally {
            conn.disconnect();
        }
    }
    
    public void addBook(TLivro book) throws ServiceException, ParserConfigurationException, SAXException, IOException {
        EXistConnection conn = new EXistConnection();
        conn.connect();
        String xml = conn.gainFile(BookManager.MY_CATALOG);
        Node root = XmlUtil.getDocumentRoot(xml);
        Node bookNode = root.appendChild(root.getOwnerDocument().createElement("livro"));
        Node bookProperty = bookNode.appendChild(root.getOwnerDocument().createElement("dono"));
        bookProperty.appendChild(root.getOwnerDocument().createTextNode(book.getDono().toString()));        
        bookProperty = bookNode.appendChild(root.getOwnerDocument().createElement("isbn"));
        bookProperty.appendChild(root.getOwnerDocument().createTextNode(book.getIsbn()));
        bookProperty = bookNode.appendChild(root.getOwnerDocument().createElement("titulo"));
        bookProperty.appendChild(root.getOwnerDocument().createTextNode(book.getTitulo()));
        for(String autor: book.getAutor()) {
            bookProperty = bookNode.appendChild(root.getOwnerDocument().createElement("autor"));
            bookProperty.appendChild(root.getOwnerDocument().createTextNode(autor));            
        }
        bookProperty = bookNode.appendChild(root.getOwnerDocument().createElement("editora"));
        bookProperty.appendChild(root.getOwnerDocument().createTextNode(book.getEditora()));      
        if (book.getObs() != null) {
            bookProperty = bookNode.appendChild(root.getOwnerDocument().createElement("obs"));
            bookProperty.appendChild(root.getOwnerDocument().createTextNode(book.getObs()));             
        }
        xml = XmlUtil.prettyPrint(root.getOwnerDocument());
        System.out.println(xml);
        conn.storeFile(BookManager.MY_CATALOG, xml);
        conn.disconnect();        
    }

    public Collection<TLivro> listBooks(String searchText) throws MalformedURLException, RemoteException, ServiceException {
        EXistConnection conn = new EXistConnection();
        conn.connect();
        Collection<TLivro> ret = listBooks(conn, searchText);
        conn.disconnect();
        
        return ret;
    }
    
    public Collection<TLivro> listRemoteBooks(int group, String searchText) throws Exception  {
        String req = XmlManager.createCatalogRequest(group);
        String xml = MySender.send(TrabUtil.getGroupHost(group), TrabUtil.getGroupPort(group), req);        
        return listBooks(xml, searchText);
    }    

    public Collection<TLivro> listBooks(EXistConnection conn, String searchText) {
        try {
            String xml = conn.gainFile(BookManager.MY_CATALOG);
            return listBooks(xml, searchText);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    
    public Collection<TLivro> listBooks(String xml, String searchText) throws XPathExpressionException {
        StringReader reader = new StringReader(xml);
        InputSource src = new InputSource(reader);
        XPath xpath = XPathFactory.newInstance().newXPath();
        NodeList list = (NodeList) xpath.evaluate(
                "//livro[count(.//text()[contains(translate(.,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz'),'"
                        + searchText.toLowerCase() + "')]) > 0]", src,
                XPathConstants.NODESET);
        return parseBooks(list);        
    }

    public Collection<TLivro> parseBooks(NodeList nodes) {
        Collection<TLivro> books = new Vector<TLivro>();
        for (int i = 0; i < nodes.getLength(); i++) {
            try {
                TLivro book = parseBook(nodes.item(i));
                books.add(book);
            } catch (DOMException e) {
                e.printStackTrace();
            } catch (XPathExpressionException e) {
                e.printStackTrace();
            }
        }
        return books;
    }

    public TLivro parseBook(Node node) throws DOMException,
            XPathExpressionException {
        ObjectFactory factory = new ObjectFactory();
        TLivro book = factory.createTLivro();
        XPath xpath = XPathFactory.newInstance().newXPath();
        String owner = ((Node) xpath.evaluate(
                "dono/text()", node, XPathConstants.NODE)).getNodeValue();
        String isbn = ((Node) xpath.evaluate("isbn/text()",
                node, XPathConstants.NODE)).getNodeValue();
        String title = ((Node) xpath.evaluate(
                "titulo/text()", node, XPathConstants.NODE)).getNodeValue();
        NodeList list = (NodeList) xpath.evaluate("autor/text()", node,
                XPathConstants.NODESET);
        for (int i = 0; i < list.getLength(); i++) {
            String author = list.item(i).getNodeValue();
            book.getAutor().add(author);
        }
        String publisher = ((Node) xpath.evaluate(
                "editora/text()", node, XPathConstants.NODE)).getNodeValue();
        String obs = null;
        Node obsNode = (Node) xpath.evaluate("obs/text()", node,
                XPathConstants.NODE);
        if (obsNode != null) {
            obs = obsNode.getNodeValue();
        }
        book.setDono(BigInteger.valueOf(Long.parseLong(owner)));
        book.setIsbn(isbn);
        book.setEditora(publisher);
        book.setTitulo(title);
        book.setObs(obs);     
        return book;
    }

    public TLivro importBook(String isbn) {
        try {
            String xml = TrabUtil.getStringFromURL("http://isbndb.com/api/books.xml?access_key="
                    + ISBNdb_KEY + "&results=authors,texts&index1=isbn&value1="
                    + isbn.replaceAll("-","").trim());
            System.out.println(XmlUtil.prettyPrint(xml));
            DocumentBuilder builder = DocumentBuilderFactory.newInstance()
                    .newDocumentBuilder();
            Document doc = builder
                    .parse(new InputSource(new StringReader(xml)));
            XPath xpath = XPathFactory.newInstance().newXPath();
            Node bookNode = (Node) xpath
                    .evaluate("/ISBNdb/BookList[1]/BookData[1]", doc,
                            XPathConstants.NODE);
            return importBook(bookNode);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public TLivro importBook(Node bookNode) throws DOMException,
            XPathExpressionException {
        if (bookNode == null) {
            return null;
        }
        XPath xpath = XPathFactory.newInstance().newXPath();
        String isbn = TrabUtil.formatISBN(((Node) xpath.evaluate("@isbn",
                bookNode, XPathConstants.NODE)).getNodeValue());
        String title = ((Node) xpath.evaluate("Title/text()", bookNode,
                XPathConstants.NODE)).getNodeValue();
        String publisher = ((Node) xpath.evaluate("PublisherText/text()",
                bookNode, XPathConstants.NODE)).getNodeValue();
        Node node = (Node) xpath.evaluate("Summary/text()", bookNode,
                XPathConstants.NODE);
        String summary = null;
        if (node != null) {
            summary = node.getNodeValue();
        }
        node = (Node) xpath.evaluate("Notes/text()", bookNode,
                XPathConstants.NODE);
        String notes = null;
        if (node != null) {
            notes = node.getNodeValue();
        }
        String obs = null;
        if ((summary != null) && (notes != null)) {
            obs = summary + "\r\n" + "\r\n" + notes;
        } else if (summary != null) {
            obs = summary;
        } else if (notes != null) {
            obs = notes;
        }
        ObjectFactory factory = new ObjectFactory();
        TLivro book = factory.createTLivro();
        book.setDono(BigInteger.valueOf(Integer.parseInt(Properties.instance
                .getProperty("mygroup"))));
        book.setIsbn(isbn);
        book.setTitulo(title);
        book.setEditora(publisher);
        book.setObs(obs);
        NodeList list = (NodeList) xpath.evaluate("Authors/Person/text()",
                bookNode, XPathConstants.NODESET);
        for (int i = 0; i < list.getLength(); i++) {
            String author = list.item(i).getNodeValue();
            System.out.println(author);
            book.getAutor().add(author);
        }
        if (book.getAutor().size() == 0) {
            String author = ((Node) xpath.evaluate("AuthorsText/text()",
                    bookNode, XPathConstants.NODE)).getNodeValue(); 
            if (author != null) {
            	book.getAutor().add(author);
            }
        }
        return book;
    }
    
    public String getControlXML() throws MalformedURLException, RemoteException, ServiceException, UnsupportedEncodingException {
        String xml = null;
        EXistConnection conn = new EXistConnection();
        try {
            conn.connect();
            xml = conn.gainFile(MY_CONTROL);
        } finally {
            conn.disconnect();
        }    
        return xml;
    }
    
    public synchronized void populateImageCache(final Collection<TLivro> books) {
    	Thread thread = new Thread(new Runnable() {
			public void run() {
		    	for(TLivro book: books) {
		    		TrabUtil.getBookImage(book.getIsbn());
		    	}
			}
    	});
    	thread.start();
    }

}
